/*
 * Copyright (c) 2017,安徽皖通科技股份有限公司 All rights reserved.
 */

package com.wttech.dzzf.process.service.initilize;

import com.wttech.dzzf.process.dao.DataInitilizingDao;
import com.wttech.dzzf.process.service.base.BaseInfoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.Future;

import static com.wttech.dzzf.process.constant.UserConstants.DEFAULT_PROCESS_NUM;

/**
 * 数据初始化拆分服务
 *
 * @author MaShibo
 * @date 2017/12/12.
 */
@Service
public class SubDataInitilizingService {

	private static final Logger LOGGER = LoggerFactory.getLogger(SubDataInitilizingService.class);

	private static final String[] TABLES = {"BS_VEHICLE", "BS_CARD", "BS_OBU"};

	@Resource
	private ThreadPoolTaskExecutor executor;

	@Resource
	private SubCardInfoProcesssService subCardInfoProcesssService;

	@Resource
	private BaseInfoService baseInfoService;

	@Resource
	private DataInitilizingDao dataInitilizingDao;

	private Map<Integer, List<String>> dateMap;

	private Integer selectValue;

	private boolean isRunning = false;

	@PostConstruct
	public void fillDateMap() {
		dateMap = new HashMap<>(3);
		dateMap.put(1, Arrays.asList("20151101"));
		dateMap.put(2, Arrays.asList("20151101", "20161101"));
		dateMap.put(3, Arrays.asList("20161101", "20171214"));
	}

	/**
	 * 数据监控：每分钟统计一次数量
	 */
	@Scheduled(fixedDelay = 1000 * 60)
	public void monitor() {
		if (!isRunning) {
			return;
		}
		LOGGER.info(baseInfoService.buildMonitorMsg(TABLES));
	}

	private void process() {
		if (selectValue == null) {
			LOGGER.info("请先选择要生成第几阶段的数据");
			return;
		}
		switch (selectValue) {
			case 1:
				processPeriodOne();
				break;
			case 2:
				processPeriodTwo();
				break;
			case 3:
				processPeriodTwo();
				break;
			default:
				LOGGER.info("无此阶段");
				break;
		}
		LOGGER.info("数据生成完成");
		executor.shutdown();
	}

	private void processPeriodOne() {
		String endOn = dateMap.get(selectValue).get(0);
		LOGGER.info("第一阶段数据生成，生成截至 【{}】的数据", endOn);
		int total = dataInitilizingDao.queryOnePeriodNum(endOn);
		LOGGER.info("共{}条数据待处理", total);
		int count = (int) Math.ceil((double) total / DEFAULT_PROCESS_NUM);
		LOGGER.info("共需要处理{}次", count);
		List<Future<Void>> futures = new ArrayList<>(count);
		for (int i = 0; i < count; i++) {
			int num = i + 1;
			/*futures.add(executor.submit(() -> {
				try {
					subCardInfoProcesssService.processPeriodOneOnce(num, endOn);
				} catch (Exception e) {
					LOGGER.error(e.getMessage(), e);
				}
				return null;
			}));*/
			subCardInfoProcesssService.processPeriodOneOnce(num, endOn);
		}
		baseInfoService.getFutureResult(futures);
	}


	private void processPeriodTwo() {
		List<String> dateList = dateMap.get(selectValue);
		String startOn = dateList.get(0);
		String endOn = dateList.get(1);
		LOGGER.info("第{}阶段，生成【{}】至【{}】的数据", new Object[]{selectValue, startOn, endOn});
		int total = dataInitilizingDao.queryTwoPeriodNum(startOn, endOn);
		LOGGER.info("共{}条数据待处理", total);
		int count = (int) Math.ceil((double) total / DEFAULT_PROCESS_NUM);
		LOGGER.info("共需要处理{}次", count);
		List<Future<Void>> futures = new ArrayList<>(count);
		for (int i = 0; i < count; i++) {
			int num = i + 1;
			futures.add(executor.submit(() -> {
				try {
					subCardInfoProcesssService.processPeriodTwoOnce(num, startOn, endOn);
				} catch (Exception e) {
					LOGGER.error(e.getMessage(), e);
				}
				return null;
			}));
		}
		baseInfoService.getFutureResult(futures);
	}

	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		SubDataInitilizingService service = context.getBean(SubDataInitilizingService.class);
		service.isRunning = true;
		service.selectValue = Integer.valueOf(args[0]);
		service.process();
	}

}
